package lt.liepasoft.locr.utils;

import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import lt.liepasoft.locr.data.RgbImage;

public class ImageUtils {
    
    private static ImageUtils instance;
    
    public BufferedImage readImage(String imgDir) throws IOException {
        return ImageIO.read(new File(imgDir));        
    }
    
    public RgbImage getImage(BufferedImage image) {
        int width = image.getWidth(null),
        height = image.getHeight(null),
        npix = width * height;
        int[] pixels = new int[npix];
        PixelGrabber grabber = new PixelGrabber(image, 0, 0, width, height, pixels, 0, width);
        try {
            grabber.grabPixels();
        } catch (InterruptedException e)    {
            System.out.println(e+"");
        }
        return new RgbImage(pixels, width, height);
    }
    
    public static ImageUtils getInstance(){
        if (instance == null)
            instance = new ImageUtils();
        return instance;
    }
    
    public BufferedImage rgbImageToImage(RgbImage RGBImage){
    //Paint the scaled image on a white background
        BufferedImage image = new BufferedImage(RGBImage.width, RGBImage.height, BufferedImage.TYPE_INT_RGB);
//        int[] pixels = new int[ocrImage.npix];
//        int px;
//        switch(ocrImage.getImageType()){
//            case RGB:{
//                pixels = ocrImage.pixels;
//            }break;
//            case GRAYSCALE:{                
//                for (int i=0; i<ocrImage.npix; i++){
//                    px = ocrImage.pixels[i];
//                    pixels[i] = new Color(px,px,px).getRGB();
//                }
//            }break;
//            case BLACK_WHITE:{
//                for (int i=0; i<ocrImage.npix; i++){
//                    px = ocrImage.pixels[i];
//                    switch (px){
//                        case 0:{
//                            pixels[i] = Color.WHITE.getRGB();
//                        }break;
//                        case 1:{
//                            pixels[i] = Color.BLACK.getRGB();
//                        }break;    
//                    }                    
//                }
//            }break;    
//        }
        image.setRGB(0, 0, RGBImage.width, RGBImage.height, RGBImage.pixels, 0, RGBImage.width);
        return image;
    }
    
    public BufferedImage rgbToImage(int[] rgbPixels, int width, int height, Component comp)
    {
        return toBufferedImage(comp.createImage(new MemoryImageSource(width, height, rgbPixels, 0, width)));
    }
    
    public BufferedImage scaleImage(BufferedImage img, double width, double height, boolean aspectRatio){
        int 
            imgWidth = img.getWidth(),
            imgHeight = img.getHeight();
        
//        if (imgWidth < width && imgHeight < height)
//            return img;
        
        AffineTransform tx = new AffineTransform();
        
        if (aspectRatio){
            double orgSize, beSize;
            if (imgWidth > imgHeight) {
                orgSize = imgWidth;
                beSize = width;
            } else {
                orgSize = imgHeight;
                beSize = height;
            }

            double 
                scaleAmount = beSize / orgSize;
             tx.scale(scaleAmount, scaleAmount);
        }  else {
             tx.scale(width/imgWidth, height/imgHeight);
        }
        
        
        //tx.scale(scaleAmount, scaleAmount);
       

        AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);

        BufferedImage result = op.filter(img, null);
        //System.out.println(width+" "+height+" "+result.getWidth()+" "+result.getHeight());
        return result;
    }
    
    
//    public BufferedImage scaleImage(BufferedImage image, double widthD, double heightD)
//    {
//            int sourceWidth = image.getWidth();
//            int sourceHeight = image.getHeight();
//            int width = (int)widthD;
//            int height = (int)heightD;
//            
//            BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//            
//            Graphics g = newImage.getGraphics();
//
//            for(int y=0; y<height; y++)
//            {
//                    for(int x=0; x<width; x++)
//                    {
//                            g.setClip(x, y, 1, 1);
//                            int dx = x * sourceWidth / (int)width;
//                            int dy = y * sourceHeight / height;
//                            g.drawImage(image, x-dx, y-dy, null);
//                    }
//            }
//
//            return newImage;
//    }      
    
//for j2me    
//    private Image scaleImage(Image image, int width, int height)
//    {
//            int sourceWidth = image.getWidth();
//            int sourceHeight = image.getHeight();
//
//            Image newImage = Image.createImage(width, height);
//            Graphics g = newImage.getGraphics();
//
//            for(int y=0; y<height; y++)
//            {
//                    for(int x=0; x<width; x++)
//                    {
//                            g.setClip(x, y, 1, 1);
//                            int dx = x * sourceWidth / width;
//                            int dy = y * sourceHeight / height;
//                            g.drawImage(image, x-dx, y-dy, Graphics.LEFT | Graphics.TOP);
//                    }
//            }
//
//            return Image.createImage(newImage);
//    }    
    
    private static BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage)image;
        }

        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();

        // Determine if the image has transparent pixels; for this method's
        // implementation, see Determining If an Image Has Transparent Pixels
        boolean hasAlpha = false;

        // Create a buffered image with a format that's compatible with the screen
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            // Determine the type of transparency of the new buffered image
            int transparency = Transparency.OPAQUE;
            if (hasAlpha) {
                transparency = Transparency.BITMASK;
            }

            // Create the buffered image
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(
                image.getWidth(null), image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }

        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            if (hasAlpha) {
                type = BufferedImage.TYPE_INT_ARGB;
            }
            bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
        }

        // Copy image to buffered image
        Graphics g = bimage.createGraphics();

        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();
        
        return bimage;
    }    
    
    private static BufferedImage convertToGrayscale(BufferedImage source) { 
        BufferedImageOp op = new ColorConvertOp(
        ColorSpace.getInstance(ColorSpace.CS_GRAY), null); 
        return op.filter(source, null);
    }    

    public RgbImage createLetterImage(String letter){
        BufferedImage img = new BufferedImage(200, 100, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = (Graphics2D)img.getGraphics();
        g.setColor(Color.white);
        g.fillRect(0, 0, img.getWidth(), img.getHeight());
        g.setColor(Color.black);       
        g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 35));
        
        g.drawString(letter, 0,25);
        return getImage(img);
    }
}
